#include <stdio.h>
#include <stdlib.h>
#include <gmp.h>
#include <time.h>

int main(){
    /* Declaração de Variáveis */
    mpf_t an, bn, tn, pn, an1, bn1, tn1, pn1, temp, parada, dez_milhoes, pi;
    FILE *f;
    long int precisao = 33333333;
    clock_t inicio = 0, fim = 0;
    int i;
    float j;
    
    /* marca o clock de inicio do programa */
    inicio = clock();

    /* seta a precsão para 10 milhões de casas decimais */
    mpf_set_default_prec(precisao);
    /* inicialização das variáveis, todas assumem valor 0*/
    mpf_init(an);
    mpf_init(an1);
    mpf_init(bn);
    mpf_init(bn1);
    mpf_init(tn);
    mpf_init(tn1);
    mpf_init(pn);
    mpf_init(pn1);
    mpf_init(temp);
    mpf_init(parada);
    mpf_init(dez_milhoes);
    mpf_init(pi);

    /* insere os valores iniciais */
    /* an = 1 */
    mpf_set_d(an, 1);

    /* bn = 1/( 2^(1/2) ) */
    mpf_set_d(temp,2);
    mpf_sqrt(temp,temp);
    mpf_ui_div(bn, 1, temp);

    /* tn = 1/4 */
    mpf_div_ui(tn, an, 4);

    /* pn = 1 */
    mpf_set_d(pn, 1);

    /* parada = an - bn */
    mpf_sub(temp, an, bn);
    mpf_abs(parada, temp);

    /* dez_milhoes = 10^(-(10^7)) */
    mpf_set_d(dez_milhoes,10);
    mpf_pow_ui(temp, dez_milhoes, 10000000);
    mpf_ui_div(dez_milhoes,1,temp);

    /* realiza as contas enquanto o numero de casas decimais for menor que 10 milhoes*/
    while(mpf_cmp(parada, dez_milhoes) > 0){
        /* an1 = (an + bn)/2 */
        mpf_add(temp, an, bn);
        mpf_div_ui(an1, temp, 2);

        /* bn1 = (an*bn)^(1/2) */
        mpf_mul(temp, an, bn);
        mpf_sqrt(bn1, temp);

        /* tn1 = tn - pn*(an - an1)^2 */
        mpf_sub(temp, an, an1);
        mpf_pow_ui(temp, temp, 2);
        mpf_mul(temp, pn, temp);
        mpf_sub(tn1, tn, temp);

        /* pn1 = 2*pn */
        mpf_mul_ui(pn1, pn,2);

        /* atualiza as variaveis Xn */
        mpf_set(an, an1);
        mpf_set(bn, bn1);
        mpf_set(tn, tn1);
        mpf_set(pn, pn1);

        /* atualiza parada */
        mpf_sub(temp, an, bn);
        mpf_abs(parada, temp);
    }
    /* imprime pi */
    mpf_add(temp, an, bn);
    mpf_pow_ui(pi, temp, 2);
    mpf_mul_ui(temp, tn, 4);
    mpf_div(pi, pi, temp);
    f = fopen("pi_gauss_legendre_sequencial.txt", "w");
    i = mpf_out_str(f, 10, 0, pi);
    
    /* marca o clock do fim do programa */
    fim = clock();
    j = (fim - inicio);
    /* imprime o numero de caracteres escritos e os segundos gastos */
    fprintf(f,"\n%d caracteres escritos\n%f segundos gastos", i, j/CLOCKS_PER_SEC);
    fclose(f);

    return 0;

}
